package nl.hva.three2learn.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import nl.hva.three2learn.authentication.UserAuthentication;
import nl.hva.three2learn.dao.ChapterDao;
import nl.hva.three2learn.dao.CourseDao;
import nl.hva.three2learn.model.Chapter;
import nl.hva.three2learn.model.Course;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping(value = "/assignment")
public final class AssignmentController extends BaseController {

	private static final Logger logger = LoggerFactory.getLogger(AssignmentController.class);
	
	@Autowired
	private CourseDao courseDao;
	
	@Autowired
	private ChapterDao chapterDao;
	
	@RequestMapping(value = "/download/{courseId}/{chapterId}")
	public void download(UserAuthentication auth,
						 HttpServletResponse response,
						 HttpServletRequest request,
						 @PathVariable("courseId") long courseId,
						 @PathVariable("chapterId") long chapterId) {
		
		Course course = courseDao.findById(courseId);
		Chapter chapter = chapterDao.findById(chapterId);
		
		// Course or chapter doesn't exist
		if (course == null || chapter == null)
			return;
		
		final String UPLOAD_DIR_NAME = "uploads";
		
		File assignmentDir = new File(
				request.getServletContext().getRealPath("/WEB-INF") // Absolute path to the WEB-INF dir
				+ File.separator
				+ UPLOAD_DIR_NAME
				+ File.separator
				+ courseId
				+ File.separator 
				+ chapterId
			);
		
		File zipFile = new File(
				assignmentDir, 
				"." + // To hide the file 
				course.getName().replaceAll(" ", "") + "_" + 
				chapter.getTitle().replaceAll(" ", "") + ".zip"
			);
		
		if (!zipFile.exists()) {
			
			ZipOutputStream out = null;
			
			try {
				
				zipFile.createNewFile();
			
				out = new ZipOutputStream(new FileOutputStream(zipFile, false));
				
				for (File f : assignmentDir.listFiles()) {
					
					// Skip directories and hidden files
					if (f.isDirectory() || f.isHidden())
						continue;
					
					// Start a new entry in the zip file
					out.putNextEntry(new ZipEntry(f.getName()));
					
					byte[] buf = new byte[1024];
					
					FileInputStream in = new FileInputStream(f);
					
					int len;
					while ((len = in.read(buf)) > 0) {
						// Write all of the content of the file
						// to the output
						out.write(buf, 0, len);
					}
					
					// Close this entry
					out.closeEntry();
				}
			} catch (IOException e) {
				logger.error("Error while trying to create assignment zip: {}", e);
			} finally {
				try {
					if (out != null)
						out.close();
				} catch (IOException e) {
					logger.error("Error while closing output stream: {}", e);
				}
			}			
		}
		
		response.setContentType("application/zip");
		response.setContentLength((int) zipFile.length());
		response.setHeader("Content-Disposition","attachment; filename=\"" + zipFile.getName() + "\"");
		
		try {
			FileInputStream in = new FileInputStream(zipFile);
			
			byte[] buf = new byte[1024];
			
			int len;
			while ((len = in.read(buf)) > 0) {
				response.getOutputStream().write(buf, 0, len);
			}
			
			in.close();
			
		} catch (FileNotFoundException e) {
			logger.error("Unable to find the assignment zip: {}", e);
		} catch (IOException e) {
			logger.error("Error reading zip file: {}", e);
		}
	}
	
}
